package fiuba.algo3;

import fiuba.algo3.caso.Caso;
import fiuba.algo3.caso.ContadorDeTiempo;
import fiuba.algo3.caso.ContadorEntradasLugares;
import fiuba.algo3.caso.OrdenDeArresto;
import fiuba.algo3.lugar.Lugar;
import fiuba.algo3.lugar.LugarBalazo;
import fiuba.algo3.lugar.LugarCuchillazo;
import fiuba.algo3.lugar.LugarDelSospechoso;
import fiuba.algo3.lugar.LugarFueraRutaDeEscape;
import fiuba.algo3.lugar.LugarRutaDeEscape;
import fiuba.algo3.mundo.Mundo;
import fiuba.algo3.mundo.Pais;

public class Partida {

	private ContadorDeTiempo contadorDeTiempo;
	private Jugador jugador;
	private ContadorEntradasLugares contadorEntradasLugares;
	private Mundo mundo;
	private Caso caso;
	
	private boolean partidaGanada = false;
	private boolean partidaPerdida = false;
	
	public Partida(Jugador jugador){
		int diaInicio = 1;
		int horaInicio = 7;

		this.mundo = new Mundo();
		
		this.caso = new Caso(this.mundo, jugador.obtenerCantidadArrestos());

		this.contadorEntradasLugares = new ContadorEntradasLugares();
		this.contadorEntradasLugares.reiniciar();

		this.contadorDeTiempo = new ContadorDeTiempo();
		this.contadorDeTiempo.reiniciar();
		this.contadorDeTiempo.incrementarEn(horaInicio, diaInicio);

		this.jugador = jugador;
		this.jugador.setearPaisInicial(this.caso.obtenerPaisInicial());
		OrdenDeArresto.reiniciar();
	}

	public boolean sospechosoCoincideConOrdenDeArresto()
	{
		
		Perfil perfilSospechoso = OrdenDeArresto.generarIdentikit();	//La orden de arresto genera identikits? Tendria que ser el sistema interpol
		Sospechoso[] sublista = SistemaInterpol.obtenerListaDeSospechosos(perfilSospechoso);

		
		if (sublista.length == 1)
			return sublista[0].comparar(caso.obtenerCulpable());
		
		return false;
	}
	
	
	public void irHasta(Pais paisDestino){
		this.verificarFactibilidadViaje(jugador.obtenerUbicacion(), paisDestino);
		int tiempoEnHoras = this.jugador.irHasta(paisDestino);
		this.sumarTiempo(0, tiempoEnHoras);
		this.contadorEntradasLugares.reiniciar();
	}
	
	private void verificarFactibilidadViaje(Pais pOrigen, Pais pDestino) {
		mundo.verificarExistenciaDePais(pDestino);
		mundo.verificarConexionEntre(pOrigen, pDestino);
	}

	public boolean finDelTiempo(){
		int diaLimite = 7;
		int horaLimite = 17;
		return this.contadorDeTiempo.esMayorA(diaLimite, horaLimite);		
	}
	
	public int obtenerDia(){
		return (this.contadorDeTiempo).obtenerDia();
	}
	
	public int obtenerHora(){
		return (this.contadorDeTiempo).obtenerHora();
	}
	
	private void incrementarEntradasLugarEconomia(){
		this.contadorEntradasLugares.incrementarEntradaLugarEconomia();
	}
	
	private void incrementarEntradasLugarViajes(){
		this.contadorEntradasLugares.incrementarEntradaLugarViajes();
	}
	
	private void incrementarEntradasBiblioteca(){
		this.contadorEntradasLugares.incrementarEntradaBiblioteca();
	}
	
	public void sumarTiempo(int dias, int horas){
		int diaInicial = this.obtenerDia();
		
		this.contadorDeTiempo.incrementarEn(horas, dias);
		
		if (this.obtenerDia() != diaInicial){
			this.sumarTiempo(0, jugador.obtenerHorasDeSuenio());
		}
	}
	
	public Pais[] obtenerPaisesConectados(){
		return this.mundo.obtenerPaisesConectados(this.jugador.obtenerUbicacion());
	}

	private int obtenerEntradasLugarEconomia(){
		return this.contadorEntradasLugares.obtenerEntradasLugarEconomia();
	}
	
	private int obtenerEntradasLugarViajes(){
		return this.contadorEntradasLugares.obtenerEntradasLugarViajes();
	}
	
	private int obtenerEntradasBiblioteca(){
		return this.contadorEntradasLugares.obtenerEntradasBiblioteca();
	}

	public String entrarEnLugarViajes(){
		
		int cantidadEntradas;
		Pais paisActual = jugador.obtenerUbicacion();
		
		this.incrementarEntradasLugarViajes();
		cantidadEntradas = this.obtenerEntradasLugarViajes();
		
		this.sumarTiempo(0, cantidadEntradas);

		return procesarLugar(paisActual.obtenerLugarViajes());
	}
	
	public String entrarEnBiblioteca(){	
		
		int cantidadEntradas;
		Pais paisActual = jugador.obtenerUbicacion();
		
		this.incrementarEntradasBiblioteca();
		cantidadEntradas = this.obtenerEntradasBiblioteca();
		
		this.sumarTiempo(0, cantidadEntradas);
		
		return procesarLugar(paisActual.obtenerBiblioteca());
	}
	
	public String entrarEnLugarEconomia(){
		
		int cantidadEntradas;
		Pais paisActual = jugador.obtenerUbicacion();
		
		this.incrementarEntradasLugarEconomia();
		cantidadEntradas = this.obtenerEntradasLugarEconomia();
		
		this.sumarTiempo(0, cantidadEntradas);		
		
		return procesarLugar(paisActual.obtenerLugarEconomia());
	}
	
	public String procesarLugar(Lugar lugar) {
		return lugar.enviarDatos(this);
	}
	
	public String procesarLugar(LugarDelSospechoso lugar)
	{
		if (this.sospechosoCoincideConOrdenDeArresto())
		{
			this.partidaGanada();
			return jugador.entrarEn(lugar);
		}
		else
		return this.partidaPerdida();
	}
	
	public String procesarLugar(LugarFueraRutaDeEscape lugar)
	{
		return jugador.entrarEn(lugar);
		
	}
	
	public String procesarLugar(LugarRutaDeEscape lugar)
	{
		return this.jugador.entrarEn(lugar);
		
	}
	
	public String procesarLugar(LugarCuchillazo lugar)
	{
		sumarTiempo(0, 2);
		
		return jugador.entrarEn(lugar);
		
	}
	
	public String procesarLugar(LugarBalazo lugar)
	{
		sumarTiempo(0, 4);
		
		return jugador.entrarEn(lugar);
		
	}

	public String obtenerNombreJugador() {
		
		return jugador.obtenerNombre();
	}

	public Pais obtenerUbicacionJugador() {
		
		return jugador.obtenerUbicacion();
	}

	public int[] obtenerDiaYHora() {
		
		int[] diaYHora = {0,0};
		
		diaYHora[0] = contadorDeTiempo.obtenerDia();
		diaYHora[1] = contadorDeTiempo.obtenerHora();
		
		return diaYHora;
		
	}

	public String obtenerNombrePaisInicial() {
		
		return caso.obtenerNombrePaisInicial();
	}

	public String obtenerNombreObjetoRobado() {
		
		return caso.obtenerObjetoRobado().obtenerNombre();
	}

	public Sospechoso[] generarListaDeSospechosos()
	{
		Perfil perfilSospechoso = OrdenDeArresto.generarIdentikit();
		
		contadorDeTiempo.incrementarEn(3, 0);
		
		return SistemaInterpol.obtenerListaDeSospechosos(perfilSospechoso);
	}

	public String obtenerSexoCulpable() {
		
		return caso.obtenerCulpable().obtenerSexo();
	}
	
	
	public String partidaPerdida()
	{
		partidaPerdida = true;
		return "La orden de arresto es incorrecta. Se ha perdido la partida";
	}
	
	public void partidaGanada()
	{
		partidaGanada = true;
		jugador.aumentarCantidadDeArrestos();
	}
	
	public boolean ganoPartida()
	{
		return partidaGanada;
	}
	
	public boolean perdioPartida()
	{
		if(finDelTiempo())
			partidaPerdida = true;
		
		return partidaPerdida;
	}

	public Partida() {
		int diaInicio = 1;
		int horaInicio = 7;

		this.mundo = new Mundo();
		
		this.caso = new Caso(this.mundo, 0);

		this.contadorEntradasLugares = new ContadorEntradasLugares();
		this.contadorEntradasLugares.reiniciar();

		this.contadorDeTiempo = new ContadorDeTiempo(horaInicio, diaInicio);

		this.jugador = new Jugador(caso.obtenerPaisInicial());
		OrdenDeArresto.reiniciar();
	}

	public String obtenerRangoJugador() {
		return jugador.obtenerTextoRango();
	}
}